package databases

import (
	"database/sql"
	"fmt"
	"log"
	"reflect"
)

//单查询
func SingleConndb(_sql string, conditions string, struc interface{}, callback func(data []string)) {
	var err error
	result := getAllKey(struc)
	switch len(result) {
	case 1:
		err = Sql_db.QueryRow(_sql, conditions).Scan(&result[0])
		break
	case 2:
		err = Sql_db.QueryRow(_sql, conditions).Scan(&result[0], &result[1])
		break
	case 3:
		err = Sql_db.QueryRow(_sql, conditions).Scan(&result[0], &result[1], &result[2])
		break
	case 4:
		err = Sql_db.QueryRow(_sql, conditions).Scan(&result[0], &result[1], &result[2], &result[3])
		break
	case 5:
		err = Sql_db.QueryRow(_sql, conditions).Scan(&result[0], &result[1], &result[2], &result[3], &result[4])
		break
	case 6:
		err = Sql_db.QueryRow(_sql, conditions).Scan(&result[0], &result[1], &result[2], &result[3], &result[4], &result[5])
		break
	case 7:
		err = Sql_db.QueryRow(_sql, conditions).Scan(&result[0], &result[1], &result[2], &result[3], &result[4], &result[5], &result[6])
		break
	case 8:
		err = Sql_db.QueryRow(_sql, conditions).Scan(&result[0], &result[1], &result[2], &result[3], &result[4], &result[5], &result[6], &result[7])
		break
	case 9:
		err = Sql_db.QueryRow(_sql, conditions).Scan(&result[0], &result[1], &result[2], &result[3], &result[4], &result[5], &result[6], &result[7], &result[8])
		break
	case 10:
		err = Sql_db.QueryRow(_sql, conditions).Scan(&result[0], &result[1], &result[2], &result[3], &result[4], &result[5], &result[6], &result[7], &result[8], &result[9])
		break
	}
	if err != nil {
		if err == sql.ErrNoRows {
			// fmt.Println("暂无数据")
			callback([]string{})
			return
		}
		log.Fatal(err)
	}
	callback(result)
}

//多查询
func MoreConndb(_sql string, callback func(data *sql.Rows)) {
	rows, _ := Sql_db.Query(_sql)
	callback(rows)
}

//增
func Add(_sql string) {
	_, err := Sql_db.Exec(_sql)
	if err != nil {
		log.Println(err)
		return
	}
	if err != nil {
		log.Println(err)
		return
	}
	fmt.Println("同步成功")
	// stmt, err := Sql_db.Prepare(_sql) //准备一个sql操作，返回一个*Stmt,用户后面的执行,这个Stmt可以被多次执行，或者并发执行
	/*
	 *    这个stmt的主要方法:Exec、Query、QueryRow、Close
	 */
	// if err != nil {
	// 	log.Println(err)
	// 	return
	// }
	// lastInsertId, err := res.LastInsertId() //批量插入的时候LastInserId返回的是第一条id,单条插入则返回这条的id
	//lastInsertId,err := res.RowsAffected()        //插入的是后RowsAffected 返回的是插入的条数
	//log.Println(reflect.TypeOf(lastInsertId))    //打印变量类型
	// last_insert_id_string := strconv.FormatInt(lastInsertId, 10) //int64 转string 需要引入 strconv包
	// log.Println("lastInsertId = " + last_insert_id_string)
}

//删
func Delete() {
	db, err := sql.Open("mysql", userName+":"+password+"@tcp("+ip+":"+port+")/"+database+"?charset=utf8")
	if err != nil {
		fmt.Printf("链接失败", err)
	} else {
		fmt.Println("链接成功")
		update_sql := "update users set name=? where id=?"
		update_stmt, update_err := db.Prepare(update_sql)
		if update_err != nil {
			log.Println(update_err)
			return
		}
		update_res, update_err := update_stmt.Exec("username", 9)
		if update_err != nil {
			log.Printf("%v", update_err)
			return
		}
		affect_count, _ := update_res.RowsAffected() //返回影响的条数,注意有两个返回值
		log.Printf("%v", affect_count)
	}
}

//改
func Update(_sql string) {
	_, err := Sql_db.Exec(_sql)
	if err != nil {
		log.Println(err)
		return
	}
	if err != nil {
		log.Println(err)
		return
	}
	fmt.Println("更改成功")
	// update_stmt, update_err := Sql_db.Prepare(update_sql)
	// if update_err != nil {
	// 	log.Println(update_err)
	// 	return
	// }
	// update_res, update_err := update_stmt.Exec("username", 9)
	// if update_err != nil {
	// 	log.Printf("%v", update_err)
	// 	return
	// }
	// affect_count, _ := update_res.RowsAffected() //返回影响的条数,注意有两个返回值
	// log.Printf("%v", affect_count)
}

//获取所有key
func getAllKey(struc interface{}) []string {
	t := reflect.TypeOf(struc)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	if t.Kind() != reflect.Struct { //判断如果不是Struct类型
		log.Println("Check type error not Struct")
	}
	fieldNum := t.NumField() //获取长度
	result := make([]string, 0, fieldNum)
	for i := 0; i < fieldNum; i++ { //遍历循环到数组里面
		result = append(result, t.Field(i).Name)
	}
	return result
}
